Skip to content

GET /api/vitals: slim scale + capacity endpoint#1094

Merged
nadaverell merged 1 commit into
mainfrom
feat/vitals-endpoint
Jul 5, 2026
Merged

GET /api/vitals: slim scale + capacity endpoint#1094
nadaverell merged 1 commit into
mainfrom
feat/vitals-endpoint

Conversation

@nadaverell

@nadaverell nadaverell commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Summary

New endpoint returning per-cluster scale and capacity — node/pod phase counts, CPU/memory usage+requests vs allocatable, metrics-server availability — without the home-page payload. Purpose-built for Radar Cloud's fleet fan-out (which previously fetched the full /api/dashboard per cluster and discarded ~90% of it), equally usable by any consumer that wants vitals without the kitchen sink.

What changed

  • GET /api/vitals (internal/server/vitals.go), mounted beside /api/dashboard in the authed API group. Pod counts are namespace-scoped to the caller's access; node counts gate on the caller's own node RBAC like the dashboard does.
  • Typed completeness contract: completeness.{accessRestricted, pending[], restricted[], complete} — sentinel lists carry k8score ResourceType values filtered to vitals-relevant kinds, and complete is derived server-side. Includes a "nodes" restricted sentinel the dashboard never had (consumers previously had to infer node RBAC blindness from zero totals). Metrics availability is deliberately not part of completeness — it's a capability, reported separately.
  • Metrics probe memoized 15s per RBAC scope: live usage hits metrics-server (8s timeout) — fine per page-load, wasteful for fleet polling. Requests/capacity stay informer-derived and fresh.
  • Stable JSON shape: pod phase counts have no omitempty — fleet consumers get fixed fields, not fields that vanish at zero.

Testing

go test ./internal/server/ green, including two new tests: happy path against the smoke fixture (counts, completeness, no false metrics claim) and node-RBAC-denial surfacing restricted: ["nodes"] + complete: false through the real permission-cache gate.

Part of the endpoint rework for cloud; the hub-side switch of its vitals fan-out to this endpoint lands separately.


Note

Medium Risk
New authenticated API surface with nuanced RBAC and namespace scoping; incorrect gates could leak pod/node aggregates, though behavior is covered by new tests and mirrors dashboard patterns.

Overview
Adds GET /api/vitals, a lightweight alternative to the full dashboard: node/pod phase counts, CPU/memory capacity vs requests vs live usage, metricsServerAvailable, and a typed completeness block (accessRestricted, pending, restricted, derived complete) so fleet consumers do not infer RBAC blindness from zeros (e.g. Node in restricted).

Shared cluster-metrics plumbing moves into node_metrics.go (fetchNodeUsage, listPodsScoped, computeCapacityRequests); the dashboard metrics path now calls those helpers instead of inlined logic. Only the metrics-server probe is memoized (~15s per kube-context + user, singleflight on bursts); capacity/requests stay informer-fresh. The memo is cleared in finalizePostContextSwitch alongside other per-cluster state.

Pod data is gated on explicit list pods RBAC (not just namespace visibility); node counts and cluster capacity sit behind list nodes, matching dashboard semantics. Pod phase fields use a stable JSON shape (no omitempty on zeros). golang.org/x/sync is a direct dependency for singleflight.

Reviewed by Cursor Bugbot for commit 22b2a1a. Bugbot is set up for automated code reviews on this repo. Configure here.

@nadaverell nadaverell requested a review from hisco as a code owner July 3, 2026 21:57
Comment thread internal/server/vitals.go
Comment thread internal/server/vitals.go Outdated
@nadaverell nadaverell force-pushed the feat/vitals-endpoint branch from 7adcc71 to e958724 Compare July 3, 2026 22:05
Comment thread internal/server/vitals.go
Comment thread internal/server/vitals.go
@nadaverell nadaverell force-pushed the feat/vitals-endpoint branch from e958724 to 30068ca Compare July 3, 2026 22:18
Comment thread internal/server/vitals.go
@nadaverell nadaverell force-pushed the feat/vitals-endpoint branch 3 times, most recently from 05862dd to f82f48d Compare July 4, 2026 00:18
Comment thread internal/server/vitals.go
@nadaverell nadaverell force-pushed the feat/vitals-endpoint branch 4 times, most recently from 82fcaa6 to 197e6be Compare July 4, 2026 00:39
Comment thread internal/server/vitals.go
@nadaverell nadaverell force-pushed the feat/vitals-endpoint branch 3 times, most recently from 9c9f0b2 to fdd7790 Compare July 5, 2026 12:46

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit fdd7790. Configure here.

Comment thread internal/server/vitals.go Outdated
@nadaverell nadaverell force-pushed the feat/vitals-endpoint branch from fdd7790 to fd71713 Compare July 5, 2026 12:56
Purpose-built for Radar Cloud's fleet fan-out, which previously
projected this corner out of the full /api/dashboard payload and
discarded the rest. Returns node/pod phase counts (namespace-scoped to
the caller's access), CPU/memory MetricSummary, and the
metrics-server-availability flag.

Completeness is typed, never stringly: accessRestricted, pending and
restricted (k8score ResourceType values, filtered to vitals-relevant
kinds), and a derived complete flag — including a "nodes" restricted
sentinel the dashboard never had (consumers previously inferred node
RBAC blindness from zero totals). Metrics-server usage is memoized for
15s per RBAC scope so fleet polling doesn't turn every request into a
live probe; requests/capacity stay informer-derived.
@nadaverell nadaverell force-pushed the feat/vitals-endpoint branch from fd71713 to 22b2a1a Compare July 5, 2026 13:19
@nadaverell nadaverell merged commit 572ab7b into main Jul 5, 2026
9 checks passed
@nadaverell nadaverell deleted the feat/vitals-endpoint branch July 5, 2026 13:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant